"""
Alpha101因子库完整演示
====================

这个脚本展示了如何使用完整的Alpha101因子库，包括：
- 所有101个因子的计算
- 性能测试和分析
- 批量计算和并行处理
- 结果分析和可视化
- 最佳实践建议

作者: Alpha101因子库团队
版本: v1.0.0
"""

import numpy as np
import pandas as pd
import time
import sys
import os
from typing import Dict, List, Tuple, Any
import warnings

# 添加项目路径
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

from alpha101.core import Alpha101Factory
from alpha101.config import get_factor_config, ALPHA_CONFIG
from data.interface import DataInterface
from data.validator import DataValidator
from data.preprocessor import DataPreprocessor
from engine.calculator import FactorCalculator

# 忽略警告
warnings.filterwarnings('ignore')


class Alpha101Demo:
    """Alpha101因子库完整演示类"""
    
    def __init__(self):
        """初始化演示环境"""
        print("🚀 Alpha101因子库完整演示")
        print("=" * 60)
        
        # 创建核心组件
        self.data_interface = DataInterface()
        self.validator = DataValidator()
        self.preprocessor = DataPreprocessor()
        self.factory = Alpha101Factory(use_numba=False)  # 演示时不使用numba以确保兼容性
        self.calculator = FactorCalculator()
        
        # 演示数据
        self.demo_data = None
        self.factor_results = {}
        
        print("✅ 核心组件初始化完成")
    
    def generate_demo_data(self, n_stocks: int = 50, n_days: int = 200) -> Dict[str, np.ndarray]:
        """
        生成演示数据
        
        Parameters:
        -----------
        n_stocks : int
            股票数量
        n_days : int
            交易日数量
            
        Returns:
        --------
        Dict[str, np.ndarray]
            演示数据
        """
        print(f"\n📊 生成演示数据: {n_stocks}只股票, {n_days}个交易日")
        
        # 使用数据接口生成示例数据
        self.demo_data = self.data_interface.create_sample_data(
            n_stocks=n_stocks, 
            n_days=n_days
        )
        
        # 验证数据质量
        validation_result = self.validator.validate_all(self.demo_data)
        if validation_result['is_valid']:
            print("✅ 数据质量验证通过")
        else:
            print("⚠️ 数据质量验证发现问题")
            for issue in validation_result['issues']:
                print(f"   - {issue}")
        
        # 数据预处理
        self.demo_data = self.preprocessor.preprocess_all(self.demo_data)
        print("✅ 数据预处理完成")
        
        return self.demo_data
    
    def demonstrate_single_factor(self, factor_id: str = 'alpha001') -> Dict[str, Any]:
        """
        演示单个因子计算
        
        Parameters:
        -----------
        factor_id : str
            因子ID
            
        Returns:
        --------
        Dict[str, Any]
            计算结果
        """
        print(f"\n🔍 演示单个因子计算: {factor_id}")
        
        # 获取因子配置
        config = get_factor_config(factor_id)
        print(f"   公式: {config['formula']}")
        print(f"   描述: {config['description']}")
        print(f"   类别: {config['category']}")
        print(f"   窗口: {config['window']}")
        
        # 计算因子
        start_time = time.time()
        result = self.calculator.compute_single_factor(factor_id, self.demo_data)
        computation_time = time.time() - start_time
        
        if 'error' not in result:
            factor_values = result['factor_values']
            print(f"✅ 计算成功，耗时: {computation_time:.4f}秒")
            print(f"   结果形状: {factor_values.shape}")
            print(f"   有效值数量: {np.sum(np.isfinite(factor_values))}")
            print(f"   NaN数量: {np.sum(np.isnan(factor_values))}")
            
            # 统计信息
            finite_values = factor_values[np.isfinite(factor_values)]
            if len(finite_values) > 0:
                print(f"   均值: {np.mean(finite_values):.6f}")
                print(f"   标准差: {np.std(finite_values):.6f}")
                print(f"   最小值: {np.min(finite_values):.6f}")
                print(f"   最大值: {np.max(finite_values):.6f}")
        else:
            print(f"❌ 计算失败: {result['error']}")
        
        return result
    
    def demonstrate_batch_calculation(self, factor_list: List[str] = None) -> Dict[str, Any]:
        """
        演示批量因子计算
        
        Parameters:
        -----------
        factor_list : List[str]
            因子列表，如果为None则使用前10个因子
            
        Returns:
        --------
        Dict[str, Any]
            批量计算结果
        """
        if factor_list is None:
            # 使用前10个因子作为演示
            all_factors = sorted(list(ALPHA_CONFIG.keys()))
            factor_list = all_factors[:10]
        
        print(f"\n🚀 演示批量因子计算: {len(factor_list)}个因子")
        print(f"   因子列表: {factor_list}")
        
        # 批量计算
        start_time = time.time()
        batch_results = self.calculator.compute_multiple_factors(
            factor_list, 
            self.demo_data,
            parallel=True
        )
        total_time = time.time() - start_time
        
        # 统计结果
        successful_factors = []
        failed_factors = []
        
        for factor_id, result in batch_results.items():
            if 'error' not in result:
                successful_factors.append(factor_id)
                self.factor_results[factor_id] = result['factor_values']
            else:
                failed_factors.append(factor_id)
                print(f"   ❌ {factor_id}: {result['error']}")
        
        print(f"✅ 批量计算完成，总耗时: {total_time:.4f}秒")
        print(f"   成功因子: {len(successful_factors)}")
        print(f"   失败因子: {len(failed_factors)}")
        print(f"   平均每因子耗时: {total_time/len(factor_list):.4f}秒")
        
        return batch_results
    
    def demonstrate_performance_analysis(self) -> Dict[str, Any]:
        """
        演示性能分析
        
        Returns:
        --------
        Dict[str, Any]
            性能分析结果
        """
        print(f"\n⚡ 演示性能分析")
        
        # 选择几个代表性因子进行性能测试
        test_factors = ['alpha001', 'alpha002', 'alpha003', 'alpha004', 'alpha005']
        performance_results = {}
        
        for factor_id in test_factors:
            if factor_id in ALPHA_CONFIG:
                print(f"   测试 {factor_id}...")
                
                # 多次运行取平均
                times = []
                for _ in range(3):
                    start_time = time.time()
                    result = self.calculator.compute_single_factor(factor_id, self.demo_data)
                    if 'error' not in result:
                        times.append(time.time() - start_time)
                
                if times:
                    avg_time = np.mean(times)
                    std_time = np.std(times)
                    performance_results[factor_id] = {
                        'avg_time': avg_time,
                        'std_time': std_time,
                        'throughput': 1.0 / avg_time
                    }
                    print(f"     平均耗时: {avg_time:.4f}±{std_time:.4f}秒")
                    print(f"     吞吐量: {1.0/avg_time:.2f}次/秒")
        
        return performance_results
    
    def demonstrate_factor_analysis(self) -> Dict[str, Any]:
        """
        演示因子分析
        
        Returns:
        --------
        Dict[str, Any]
            因子分析结果
        """
        print(f"\n📈 演示因子分析")
        
        if not self.factor_results:
            print("   ⚠️ 没有可用的因子结果，请先运行批量计算")
            return {}
        
        analysis_results = {}
        
        # 分析每个因子的统计特性
        for factor_id, factor_values in self.factor_results.items():
            finite_values = factor_values[np.isfinite(factor_values)]
            
            if len(finite_values) > 0:
                analysis = {
                    'count': len(finite_values),
                    'mean': np.mean(finite_values),
                    'std': np.std(finite_values),
                    'min': np.min(finite_values),
                    'max': np.max(finite_values),
                    'skewness': self._calculate_skewness(finite_values),
                    'kurtosis': self._calculate_kurtosis(finite_values)
                }
                analysis_results[factor_id] = analysis
                
                print(f"   {factor_id}:")
                print(f"     有效值: {analysis['count']}")
                print(f"     均值: {analysis['mean']:.6f}")
                print(f"     标准差: {analysis['std']:.6f}")
                print(f"     偏度: {analysis['skewness']:.4f}")
                print(f"     峰度: {analysis['kurtosis']:.4f}")
        
        return analysis_results
    
    def demonstrate_correlation_analysis(self) -> np.ndarray:
        """
        演示因子相关性分析
        
        Returns:
        --------
        np.ndarray
            相关性矩阵
        """
        print(f"\n🔗 演示因子相关性分析")
        
        if len(self.factor_results) < 2:
            print("   ⚠️ 需要至少2个因子进行相关性分析")
            return np.array([])
        
        # 构建因子矩阵
        factor_names = list(self.factor_results.keys())
        n_factors = len(factor_names)
        n_stocks, n_days = next(iter(self.factor_results.values())).shape
        
        # 计算每个因子的截面均值（时间序列）
        factor_series = {}
        for factor_id, factor_values in self.factor_results.items():
            # 计算每日的截面均值
            daily_means = []
            for day in range(n_days):
                day_values = factor_values[:, day]
                finite_values = day_values[np.isfinite(day_values)]
                if len(finite_values) > 0:
                    daily_means.append(np.mean(finite_values))
                else:
                    daily_means.append(np.nan)
            factor_series[factor_id] = np.array(daily_means)
        
        # 计算相关性矩阵
        correlation_matrix = np.full((n_factors, n_factors), np.nan)
        
        for i, factor1 in enumerate(factor_names):
            for j, factor2 in enumerate(factor_names):
                series1 = factor_series[factor1]
                series2 = factor_series[factor2]
                
                # 找到两个序列都有效的时间点
                valid_mask = np.isfinite(series1) & np.isfinite(series2)
                if np.sum(valid_mask) > 10:  # 至少需要10个有效观测
                    correlation_matrix[i, j] = np.corrcoef(
                        series1[valid_mask], 
                        series2[valid_mask]
                    )[0, 1]
        
        print(f"   相关性矩阵 ({n_factors}×{n_factors}):")
        print("   因子名称:", factor_names)
        
        # 显示相关性统计
        finite_corrs = correlation_matrix[np.isfinite(correlation_matrix)]
        if len(finite_corrs) > 0:
            print(f"   平均相关性: {np.mean(finite_corrs):.4f}")
            print(f"   相关性标准差: {np.std(finite_corrs):.4f}")
            print(f"   最大相关性: {np.max(finite_corrs):.4f}")
            print(f"   最小相关性: {np.min(finite_corrs):.4f}")
        
        return correlation_matrix
    
    def demonstrate_comprehensive_test(self) -> Dict[str, Any]:
        """
        演示综合测试
        
        Returns:
        --------
        Dict[str, Any]
            综合测试结果
        """
        print(f"\n🧪 演示综合测试")
        
        # 测试所有因子（分批进行以避免内存问题）
        all_factors = sorted(list(ALPHA_CONFIG.keys()))
        batch_size = 20
        total_batches = (len(all_factors) + batch_size - 1) // batch_size
        
        test_results = {
            'total_factors': len(all_factors),
            'successful_factors': [],
            'failed_factors': [],
            'performance_stats': {}
        }
        
        print(f"   测试 {len(all_factors)} 个因子，分 {total_batches} 批进行")
        
        for batch_idx in range(total_batches):
            start_idx = batch_idx * batch_size
            end_idx = min(start_idx + batch_size, len(all_factors))
            batch_factors = all_factors[start_idx:end_idx]
            
            print(f"   批次 {batch_idx + 1}/{total_batches}: {len(batch_factors)} 个因子")
            
            batch_start_time = time.time()
            batch_results = self.calculator.compute_multiple_factors(
                batch_factors, 
                self.demo_data
            )
            batch_time = time.time() - batch_start_time
            
            # 统计批次结果
            batch_successful = 0
            for factor_id, result in batch_results.items():
                if 'error' not in result:
                    test_results['successful_factors'].append(factor_id)
                    batch_successful += 1
                else:
                    test_results['failed_factors'].append(factor_id)
            
            print(f"     成功: {batch_successful}/{len(batch_factors)}, 耗时: {batch_time:.2f}秒")
        
        # 计算总体统计
        success_rate = len(test_results['successful_factors']) / len(all_factors) * 100
        test_results['success_rate'] = success_rate
        
        print(f"\n✅ 综合测试完成:")
        print(f"   总因子数: {test_results['total_factors']}")
        print(f"   成功因子: {len(test_results['successful_factors'])}")
        print(f"   失败因子: {len(test_results['failed_factors'])}")
        print(f"   成功率: {success_rate:.1f}%")
        
        if test_results['failed_factors']:
            print(f"   失败因子列表: {test_results['failed_factors'][:10]}...")
        
        return test_results
    
    def _calculate_skewness(self, data: np.ndarray) -> float:
        """计算偏度"""
        if len(data) < 3:
            return np.nan
        mean = np.mean(data)
        std = np.std(data)
        if std == 0:
            return np.nan
        return np.mean(((data - mean) / std) ** 3)
    
    def _calculate_kurtosis(self, data: np.ndarray) -> float:
        """计算峰度"""
        if len(data) < 4:
            return np.nan
        mean = np.mean(data)
        std = np.std(data)
        if std == 0:
            return np.nan
        return np.mean(((data - mean) / std) ** 4) - 3
    
    def generate_summary_report(self) -> str:
        """
        生成总结报告
        
        Returns:
        --------
        str
            总结报告
        """
        report = []
        report.append("\n" + "=" * 60)
        report.append("Alpha101因子库演示总结报告")
        report.append("=" * 60)
        
        # 基本信息
        if self.demo_data is not None:
            n_stocks, n_days = self.demo_data['close'].shape
            report.append(f"数据规模: {n_stocks} 股票 × {n_days} 交易日")
        
        # 因子统计
        total_factors = len(ALPHA_CONFIG)
        computed_factors = len(self.factor_results)
        report.append(f"总因子数: {total_factors}")
        report.append(f"已计算因子: {computed_factors}")
        
        # 性能信息
        report.append(f"计算引擎: {'Numba加速' if self.factory.use_numba else '纯Python'}")
        
        # 建议
        report.append("\n推荐使用方式:")
        report.append("1. 对于生产环境，建议启用Numba加速")
        report.append("2. 大规模计算时使用并行处理")
        report.append("3. 定期验证因子计算结果的正确性")
        report.append("4. 根据具体需求选择合适的因子子集")
        
        report.append("\n" + "=" * 60)
        report.append("演示完成！感谢使用Alpha101因子库！")
        report.append("=" * 60)
        
        return "\n".join(report)


def run_complete_demo():
    """运行完整演示"""
    try:
        # 创建演示实例
        demo = Alpha101Demo()
        
        # 1. 生成演示数据
        demo.generate_demo_data(n_stocks=30, n_days=150)
        
        # 2. 演示单个因子计算
        demo.demonstrate_single_factor('alpha001')
        
        # 3. 演示批量计算
        demo.demonstrate_batch_calculation()
        
        # 4. 演示性能分析
        demo.demonstrate_performance_analysis()
        
        # 5. 演示因子分析
        demo.demonstrate_factor_analysis()
        
        # 6. 演示相关性分析
        demo.demonstrate_correlation_analysis()
        
        # 7. 演示综合测试（可选，耗时较长）
        print("\n❓ 是否运行完整的101因子综合测试？（耗时较长）")
        print("   输入 'y' 运行，其他键跳过...")
        
        # 在实际使用中可以取消注释下面的代码来等待用户输入
        # user_input = input().strip().lower()
        # if user_input == 'y':
        #     demo.demonstrate_comprehensive_test()
        # else:
        #     print("   跳过综合测试")
        
        # 8. 生成总结报告
        summary = demo.generate_summary_report()
        print(summary)
        
        return True
        
    except Exception as e:
        print(f"\n❌ 演示过程中发生错误: {e}")
        import traceback
        traceback.print_exc()
        return False


def main():
    """主函数"""
    print("Alpha101因子库完整演示")
    print(f"启动时间: {pd.Timestamp.now()}")
    
    success = run_complete_demo()
    
    if success:
        print("\n🎉 演示成功完成！")
        print("\n📚 更多信息请参考:")
        print("   - README.md: 项目介绍和快速开始")
        print("   - PROJECT_SUMMARY.md: 项目总结")
        print("   - examples/: 更多使用示例")
        print("   - tests/: 测试文件")
    else:
        print("\n❌ 演示未能完成，请检查错误信息")
    
    return success


if __name__ == "__main__":
    success = main()
    sys.exit(0 if success else 1)